package com.rslai.commons.util.xmind;

import com.rslai.commons.util.EnumUtil;
import com.rslai.commons.util.xmind.enums.ImageAlignEnum;
import com.rslai.commons.util.xmind.enums.MarkerEnum;
import com.rslai.commons.util.xmind.pojo.Attached;
import com.rslai.commons.util.xmind.pojo.Image;
import org.xmind.core.*;
import org.xmind.core.io.ByteArrayStorage;
import org.xmind.core.marker.IMarkerRef;

import java.io.IOException;
import java.util.ArrayList;

/**
 * 读取 XMind 文件
 */
public class XmindRead {
    /**
     * 读取 XMind 文件
     * @param filePath XMind文件路径
     * @return
     * @throws CoreException
     * @throws IOException
     */
    public Attached read(String filePath) throws CoreException, IOException {
        IWorkbookBuilder builder = Core.getWorkbookBuilder(); // 创建 workbookBuilder 对象
        IEncryptionHandler iench = () -> "privet";
        IWorkbook workbook = builder.loadFromPath(filePath, new ByteArrayStorage(), iench); // 加载 XMind 文件
        ISheet isheet = workbook.getPrimarySheet(); // 获得第一个 sheet
        IManifest manifest = workbook.getManifest(); // 获得文档中的资源（文件）
        ITopic root = isheet.getRootTopic(); // 获得根节点

        return setRootAttached(manifest, root); // 递归设置子主题的节点对象
    }

    /**
     * 设置根节点的附件对象
     * @param manifest 文档中的资源（文件）
     * @param root root topic 对象
     * @return
     * @throws IOException
     */
    private Attached setRootAttached(IManifest manifest, ITopic root) throws IOException {
        if (root == null) {
            return null;
        }

        Attached attached = setAttachedInfo(manifest, root); // 设置根节点信息

        // 遍历子节点，设置子节点信息
        for (ITopic child : root.getAllChildren()) {
            if (attached.getChildren() == null) {
                attached.setChildren(new ArrayList<>());
            }
            recursivelySetAttached(manifest, child, attached); // 递归设置子节点的子节点
        }

        return attached;
    }

    /**
     * 递归设置子主题的 节点对象
     * @param manifest 文档中的资源（文件）
     * @param topic topic 对象
     * @param attached 当前节点的信息
     * @throws IOException
     */
    private void recursivelySetAttached(IManifest manifest, ITopic topic, Attached attached) throws IOException {
        Attached childAttached = setAttachedInfo(manifest, topic); // 设置子节点信息
        attached.getChildren().add(childAttached);

        // 遍历子节点，设置子节点信息
        for (ITopic child : topic.getAllChildren()) {
            if (childAttached.getChildren() == null) {
                childAttached.setChildren(new ArrayList<>());
            }
            recursivelySetAttached(manifest, child, childAttached); // 递归设置子节点的子节点
        }
    }

    /**
     * 设置 节点对象 信息
     * @param manifest 文档中的资源（文件）
     * @param topic topic 对象
     * @return
     * @throws IOException
     */
    private Attached setAttachedInfo(IManifest manifest, ITopic topic) {
        Attached attached = new Attached();
        attached.setId(topic.getId()); // 设置子主题的 ID
        attached.setTitle(topic.getTitleText()); // 设置子主题的标题
        attached.setFolded(topic.isFolded()); // 设置子主题是否折叠

        // 设置子主题的备注
        if (topic.getNotes().getContent(INotes.PLAIN) != null) {
            IPlainNotesContent notesContent = (IPlainNotesContent) topic.getNotes().getContent(INotes.PLAIN);
            attached.setNotes(notesContent.getTextContent());
        }

        // 设置子主题的 图标（marker）
        if (topic.getMarkerRefs() != null && topic.getMarkerRefs().size() > 0) {
            attached.setMarkers(new ArrayList<>());
            for (IMarkerRef markerRef : topic.getMarkerRefs()) {
                attached.getMarkers().add(EnumUtil.valueOf(MarkerEnum.class, markerRef.getMarkerId()));
            }
        }

        // 设置子主题的标签（label）
        if (topic.getLabels() != null && topic.getLabels().size() > 0) {
            attached.setLabels(new ArrayList<>());
            for (String label : topic.getLabels()) {
                attached.getLabels().add(label);
            }
        }

        // 设置子主题的图片
        if (topic.getImage().getSource() != null) {
            Image image = new Image();
            image.setSrc(topic.getImage().getSource());  // 设置图片路径
            image.setHeight(topic.getImage().getHeight()); // 设置图片高度
            image.setWidth(topic.getImage().getWidth()); // 设置图片宽度
            image.setAlignment(EnumUtil.valueOf(ImageAlignEnum.class, topic.getImage().getAlignment())); // 设置图片对齐方式
            IFileEntry fileEntry = manifest.getFileEntry(topic.getImage().getSource().replace("xap:", "")); // 从 xmind 文档中获取图片文件
            image.setInputStream(fileEntry.getInputStream()); // 设置图片输入流
            attached.setImage(image);
        }
        return attached;
    }
}
